package cn.xshi.common.util.QR;

import cn.xshi.common.util.ExceptionUtil;
import cn.xshi.common.util.StringUtil;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.swetake.util.Qrcode;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.exception.DecodingFailedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import jp.sourceforge.qrcode.util.Color;
import org.apache.commons.net.util.Base64;
import java.io.File;

/**
 * @Desc 二维码工具类
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
public class QRUtil {

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param imgPath 图片路径
     */
    public static void encoderQRCode(String content, String imgPath) {
        encoderQRCode(content, imgPath, "png", 2);
    }

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param output 输出流
     */
    public static void encoderQRCode(String content, OutputStream output) {
        encoderQRCode(content, output, "png", 2);
    }

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     */
    public static void encoderQRCode(String content, String imgPath, String imgType) {
        encoderQRCode(content, imgPath, imgType, 2);
    }

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param output 输出流
     * @param imgType 图片类型
     */
    public static void encoderQRCode(String content, OutputStream output, String imgType) {
        encoderQRCode(content, output, imgType, 2);
    }

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param imgPath 图片路径
     * @param imgType 图片类型
     * @param size 二维码尺寸
     */
    public static void encoderQRCode(String content, String imgPath, String imgType, int size) {
        try {
            BufferedImage bufferedImage = qRCodeCommon(content, imgType, size);
            File imgFile = new File(imgPath);
            ImageIO.write(bufferedImage, imgType, imgFile);
        } catch (Exception e) {
            log.error("生成二维码异常：{}",e);
        }
    }

    /**
     * 生成二维码图片（基于QRCode）
     * @param content 存储内容
     * @param output 输出流
     * @param imgType 图片类型
     * @param size 二维码尺寸
     */
    public static void encoderQRCode(String content, OutputStream output, String imgType, int size) {
        try {
            BufferedImage bufferedImage = qRCodeCommon(content, imgType, size);
            // 生成二维码QRCode图片
            ImageIO.write(bufferedImage, imgType, output);
        } catch (Exception e) {
            log.error("生成二维码异常：{}",e);
        }
    }

    /**
     * 生成二维码图片的公共方法（基于QRCode）
     * @param content 存储内容
     * @param imgType 图片类型
     * @param size 二维码尺寸
     * @return
     */
    private static BufferedImage qRCodeCommon(String content, String imgType, int size) {
        BufferedImage bufferedImage = null;
        size = 10;
        try {
            Qrcode qrcodeHandler = new Qrcode();
            // 设置二维码排错率，可选L(7%)、M(15%)、Q(25%)、H(30%)，排错率越高可存储的信息越少，但对二维码清晰度的要求越小
            qrcodeHandler.setQrcodeErrorCorrect('M');
            qrcodeHandler.setQrcodeEncodeMode('B');
            // 设置设置二维码尺寸，取值范围1-40，值越大尺寸越大，可存储的信息越大
            qrcodeHandler.setQrcodeVersion(size);
            // 获得内容的字节数组，设置编码格式
            byte[] contentBytes = content.getBytes("utf-8");
            // 图片尺寸
            //int imgSize = 67 + 12 * (size - 1);
            int imgSize = 67 + 12 * (size - 1);
            bufferedImage = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);
            Graphics2D gs = bufferedImage.createGraphics();
            // 设置背景颜色
            gs.setBackground(java.awt.Color.WHITE);
            gs.clearRect(0, 0, imgSize, imgSize);
            // 设定图像颜色> BLACK
            gs.setColor(java.awt.Color.BLACK);
            // 设置偏移量，不设置可能导致解析出错
            int pixoff = 2;
            // 输出内容> 二维码
            if (contentBytes.length > 0 && contentBytes.length < 800) {
                boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
                for (int i = 0; i < codeOut.length; i++) {
                    for (int j = 0; j < codeOut.length; j++) {
                        if (codeOut[j][i]) {
                            gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
                        }
                    }
                }
            } else {
                throw new ExceptionUtil("QRCode content bytes length = " + contentBytes.length + " not in [0, 800].");
            }
            gs.dispose();
            bufferedImage.flush();
        } catch (Exception e) {
            log.error("生成二维码异常：{}",e);
        }
        return bufferedImage;
    }

    /**
     * 解析二维码（基于QRCode）
     * @param imgPath 图片路径
     * @return
     */
    public static String decoderQRCode(String imgPath) throws Exception{
        File imageFile = new File(imgPath);
        BufferedImage bufferedImage = null;
        String content = null;
        try {
            bufferedImage = ImageIO.read(imageFile);
            QRCodeDecoder decoder = new QRCodeDecoder();
            content = new String(decoder.decode(new QRCodeImageDTO(bufferedImage)), "utf-8");
        } catch (IOException ioException) {
            log.error("解析二维码异常: " + ioException.getMessage());
        } catch (DecodingFailedException decodingFailedException) {
            log.error("解析二维码异常: " + decodingFailedException.getMessage());
        }
        return content;
    }

    /**
     * 解析二维码（基于QRCode）
     * @param input 输入流
     * @return
     */
    public static String decoderQRCode(InputStream input) {
        BufferedImage bufImg = null;
        String content = null;
        try {
            bufImg = ImageIO.read(input);
            QRCodeDecoder decoder = new QRCodeDecoder();
            content = new String(decoder.decode(new QRCodeImageDTO(bufImg)), "utf-8");
        } catch (IOException e) {
            log.error("解析二维码异常: " + e.getMessage());
        } catch (DecodingFailedException e) {
            log.error("解析二维码异常: " + e.getMessage());
        }
        return content;
    }

    /**
     * 生成二维码（基于com.google.zxing）
     * @param imgPath
     * @param format
     * @param content
     * @param width
     * @param height
     * @param logo
     * @throws Exception
     */
    public static void encodeImage(String imgPath,String format,String content,int width,int height,String logo) throws Exception {
        Hashtable<EncodeHintType,Object > hints = new Hashtable<EncodeHintType,Object>() ;
        //排错率  L<M<Q<H
        hints.put( EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H) ;
        //编码
        hints.put( EncodeHintType.CHARACTER_SET, "utf-8") ;
        //外边距：margin
        hints.put( EncodeHintType.MARGIN, 1) ;
        /*
         * content : 需要加密的 文字
         * BarcodeFormat.QR_CODE:要解析的类型（二维码）
         * hints：加密涉及的一些参数：编码、排错率
         */
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,width,height, hints);
        //内存中的一张图片：此时需要的图片 是二维码-> 需要一个boolean[][] ->BitMatrix
        BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        for(int x=0;x<width;x++) {
            for(int y=0;y<height;y++) {
                bufferedImage.setRGB(x, y, (bitMatrix.get(x,y)? Color.BLACK:Color.WHITE)  );
            }
        }
        //画logo
        bufferedImage = addLogo(bufferedImage, logo) ;
        File file = new File(imgPath);
        //生成图片
        ImageIO.write(bufferedImage, format, file);
    }

    /**
     * 解密：二维码->文字（基于com.google.zxing）
     * @param file
     * @throws Exception
     */
    public static String decodeImage(File file) throws Exception {
        if(!file.exists()) return null;
        BufferedImage bufferedImage = ImageIO.read(file);
        MultiFormatReader formatReader = new MultiFormatReader() ;
        LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        Map map = new HashMap();
        map.put(EncodeHintType.CHARACTER_SET, "utf-8") ;
        Result result = formatReader.decode(binaryBitmap  ,map ) ;
        log.info("解析结果："+ result.toString());
        return result.toString();
    }

    /**
     * 传递logo头像（基于com.google.zxing）
     * @param bufferedImage
     * @param logo
     * @return
     * @throws IOException
     */
    public static BufferedImage addLogo( BufferedImage bufferedImage,String logo) throws IOException {
        //在二维码上画logo:产生一个  二维码画板
        Graphics2D g2 = bufferedImage.createGraphics();

        //画logo： String->BufferedImage(内存)
        BufferedImage logoImg = ImageIO.read(new File(logo));
        int height = bufferedImage.getHeight();
        int width = bufferedImage.getWidth();
        //纯logo图片
        g2.drawImage(logoImg, width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, null);

        //产生一个 画 白色圆角正方形的 画笔
        BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //将画板-画笔 关联
        g2.setStroke(stroke);
        //创建一个正方形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setColor(java.awt.Color.WHITE);
        g2.draw(round);

        //灰色边框
        BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setStroke(stroke2);
        //创建一个正方形
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width * 2 / 5 + 2, height * 2 / 5 + 2, width * 1 / 5 - 4, height * 1 / 5 - 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //Color color = new Color(128,128,128) ;
        g2.setColor(java.awt.Color.GRAY);
        g2.draw(round2);
        g2.dispose();
        bufferedImage.flush();
        return bufferedImage;
    }

    /**
     * 生成二维码（基于com.google.zxing）
     * @param format
     * @param content
     * @param width
     * @param height
     * @param logoBase64
     * @throws Exception
     */
    public static String encodeImageBase64(String format,String content,int width,int height,String logoBase64) throws Exception {
        String base64 = null;
        Hashtable<EncodeHintType,Object > hints = new Hashtable<EncodeHintType,Object>() ;
        //排错率  L<M<Q<H
        hints.put( EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H) ;
        //编码
        hints.put( EncodeHintType.CHARACTER_SET, "utf-8") ;
        //外边距：margin
        hints.put( EncodeHintType.MARGIN, 1) ;
        /*
         * content : 需要加密的 文字
         * BarcodeFormat.QR_CODE:要解析的类型（二维码）
         * hints：加密涉及的一些参数：编码、排错率
         */
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,width,height, hints);
        //内存中的一张图片：此时需要的图片 是二维码-> 需要一个boolean[][] ->BitMatrix
        BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        for(int x=0;x<width;x++) {
            for(int y=0;y<height;y++) {
                bufferedImage.setRGB(x, y, (bitMatrix.get(x,y)? Color.BLACK:Color.WHITE)  );
            }
        }
        //画logo
        bufferedImage = addLogoBase64(bufferedImage, logoBase64) ;
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        //生成图片
        ImageIO.write(bufferedImage, format, outputStream);
        byte[] bytes=outputStream.toByteArray();
        base64 = "data:image/png;base64,"+Base64.encodeBase64String(bytes);
        return base64;
    }

    /**
     * 解密：二维码->文字（基于com.google.zxing）
     * @param base64
     * @throws Exception
     */
    public static String decodeImageBase64(String base64) throws Exception {
        if(StringUtil.isEmpty(base64)){
            return null;
        }
        base64 = base64.replaceAll("data:image/png;base64,","");
        InputStream inputStream = convertBase64ToInputStream(base64);//logo流
        if(null == inputStream){
            throw new ExceptionUtil("二维码流为空");
        }
        BufferedImage bufferedImage = ImageIO.read(inputStream);
        MultiFormatReader formatReader = new MultiFormatReader() ;
        LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        Map map = new HashMap();
        map.put(EncodeHintType.CHARACTER_SET, "utf-8") ;
        Result result = formatReader.decode(binaryBitmap  ,map ) ;
        log.info("解析结果："+ result.toString());
        return result.toString();
    }

    /**
     * 传递logo头像（基于com.google.zxing）
     * @param bufferedImage
     * @param logoBase64
     * @return
     * @throws IOException
     */
    public static BufferedImage addLogoBase64( BufferedImage bufferedImage,String logoBase64) throws IOException {
        if(StringUtil.isEmpty(logoBase64)){
            return bufferedImage;
        }
        logoBase64 = logoBase64.replaceAll("data:image/png;base64,","");
        //在二维码上画logo:产生一个  二维码画板
        Graphics2D g2 = bufferedImage.createGraphics();

        //画logo： String->BufferedImage(内存)
        InputStream logoInputStream = convertBase64ToInputStream(logoBase64);//logo流
        if(null == logoInputStream){
            throw new ExceptionUtil("logo流为空");
        }
        BufferedImage logoImg = ImageIO.read(logoInputStream);//采用流方式
        int height = bufferedImage.getHeight();
        int width = bufferedImage.getWidth();
        //纯logo图片
        g2.drawImage(logoImg, width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, null);

        //产生一个 画 白色圆角正方形的 画笔
        BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //将画板-画笔 关联
        g2.setStroke(stroke);
        //创建一个正方形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setColor(java.awt.Color.WHITE);
        g2.draw(round);

        //灰色边框
        BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setStroke(stroke2);
        //创建一个正方形
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width * 2 / 5 + 2, height * 2 / 5 + 2, width * 1 / 5 - 4, height * 1 / 5 - 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //Color color = new Color(128,128,128) ;
        g2.setColor(java.awt.Color.GRAY);
        g2.draw(round2);
        g2.dispose();
        bufferedImage.flush();
        return bufferedImage;
    }

    /**
     * 转换Base64为InputStream
     * @param base64
     * @return
     */
    public static InputStream convertBase64ToInputStream(String base64){
        if(StringUtil.isEmpty(base64)){
            return null;
        }
        try {
            byte[] byteArr = Base64.decodeBase64(base64);
            InputStream inputStream = new ByteArrayInputStream(byteArr);
            return inputStream;
        }catch (Exception e){
            log.error("base64转流异常,{}",e);
            return null;
        }
    }
//
//    /**
//     * 测试类
//     * @param args
//     */
//    public static void main(String[] args) {
//        QRUtil qrUtil = new QRUtil();
////        1.（基于QRCode）
//        try {
//            String imgPath = "D:/test.png";
//            String encoderContent = "http://www.jehc.top";
//            qrUtil.encoderQRCode(encoderContent, imgPath, "png");
//            OutputStream output = new FileOutputStream(imgPath);
//            qrUtil.encoderQRCode(encoderContent, output);
//            String decoderContent = qrUtil.decoderQRCode(imgPath);
//            System.out.println(decoderContent);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//
//        //2.（基于com.google.zxing）
//        try {
//            String imgPath = "D:/test.png";
//            String content = "http://www.jehc.top";
//            String logo = "D:/logo.png";
//            //加密：文字信息->二维码
//            qrUtil.encodeImage(imgPath, "png",content, 430, 430,logo);
//            //解密：二维码  ->文字信息
//            qrUtil.decodeImage(new File(imgPath));
//        }catch (Exception e){
//
//        }
//
//        //2.（基于com.google.zxing）
//        try {
//            String content = "http://www.jehc.top";
//            String logoBase64 = "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";
//            //加密：文字信息->二维码
//            String base64 = qrUtil.encodeImageBase64( "png",content, 430, 430,logoBase64);
//            log.info("生成二维码：{}",base64);
//            //解密：二维码  ->文字信息
//            String res = qrUtil.decodeImageBase64(base64);
//            log.info("解析码：{}",res);
//        }catch (Exception e){
//
//        }
//    }
}